package ua.com.stormlabs.tiny.licenseserver.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import ua.com.stormlabs.tiny.licenseserver.storage.SecurityUsersRepository;
import ua.com.stormlabs.tiny.licenseserver.storage.entities.SecurityUserEntity;
import ua.com.stormlabs.tiny.licenseserver.utils.ArgumentGuard;

import java.util.LinkedList;
import java.util.List;

/**
 * @author Maxim Bondarenko
 * @version 1.0 1/17/12
 */

public class SecurityUsersService implements UserDetailsService {

    private static final Logger log = LoggerFactory.getLogger(SecurityUsersService.class);

    private static final GrantedAuthority ADMIN_AUTHORITY = new SimpleGrantedAuthority("ROLE_ADMIN");
    private static final GrantedAuthority STAFF_AUTHORITY = new SimpleGrantedAuthority("ROLE_STAFF");
    private static final GrantedAuthority USER_AUTHORITY = new SimpleGrantedAuthority("ROLE_USER");
    private static final GrantedAuthority DEFAULT_AUTHORITY = new SimpleGrantedAuthority("ROLE_ANONYMOUS");

    @Autowired
    SecurityUsersRepository securityUsersRepository;

    @Transactional(readOnly = true)
    @Override
    public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
        ArgumentGuard.checkNotNull(login, "login");
        ArgumentGuard.checkNotBlank(login, "login");

        SecurityUserEntity securityUser = securityUsersRepository.findByLogin(login);

        if (securityUser == null) {
            String msg = "User [" + login + "] not found";
            log.error(msg);
            throw new UsernameNotFoundException(msg);
        }
        log.info("User for login [" + login + "] found ID [" + securityUser.getId() + "]");

        List<GrantedAuthority> grantedAuthorities = new LinkedList<GrantedAuthority>();
        switch (securityUser.getRoleType()) {
            case ROLE_ADMIN:
                grantedAuthorities.add(ADMIN_AUTHORITY);
                break;
            case ROLE_STAFF:
                grantedAuthorities.add(STAFF_AUTHORITY);
                break;
            case ROLE_USER:
                grantedAuthorities.add(USER_AUTHORITY);
                break;
            default:
                grantedAuthorities.add(DEFAULT_AUTHORITY);
        }

        return new User(securityUser.getLogin(), securityUser.getPasswordHash(), grantedAuthorities);
    }
}
